package com.kirayous.api.service.impl;

import com.kirayous.api.admin.mapper.RoleMapper;
import com.kirayous.common.dto.RoleResourceDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;

/**
 * @author KiraYous
 * @version V1.0
 * @Package com.kirayous.handler
 * @date 2021/9/26 16:07
 */
@Component
public class FilterInvocationSecurityMetadataSourceImpl implements FilterInvocationSecurityMetadataSource {

    /**
     * 资源角色列表
     *
     */
    private static List<RoleResourceDTO> roleResourceList;

    @Autowired
    private RoleMapper roleMapper;

    /**
     * 加载资源角色信息
     *
     *
     * @PostConstruct是JAVA的方法，并不是spring提供的
     * 作用是在服务启动的时候，就执行这个方法,spring框架会识别这个注解，在依赖注入之后执行
     * Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     */
    @PostConstruct
    private void loadDataSource() {


        roleResourceList = roleMapper.listRoleResources();
//        roleResourceList.forEach(System.out::println);
    }

    /**
     * 清空接口角色信息
     */
    public void clearDataSource() {
        roleResourceList = null;
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        // 修改接口角色关系后重新加载
        if (CollectionUtils.isEmpty(roleResourceList)) {
            this.loadDataSource();
        }
        FilterInvocation fi = (FilterInvocation) object;
        // 获取用户请求方式
        String method = fi.getRequest().getMethod();
        // 获取用户请求Url
        String url = fi.getRequest().getRequestURI();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        // 获取接口角色信息，若为匿名接口则放行，若无对应角色则禁止
        for (RoleResourceDTO RoleResourceDTO : roleResourceList) {
            if (antPathMatcher.match(RoleResourceDTO.getUrl(), url) && RoleResourceDTO.getRequestMethod().equals(method)) {
                List<String> roleList = RoleResourceDTO.getRoleList();

                // TODO 不是很懂这里
                if (CollectionUtils.isEmpty(roleList)) {
                    return SecurityConfig.createList("disable");
                }
                return SecurityConfig.createList(roleList.toArray(new String[]{}));
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }

}
